<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Drag &amp; Drop in Mono Winforms</title>
<link rel="stylesheet" href="/cfg//format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Mono, C#, drag and drop, Winforms, tutorial, GUI, programming">
<meta name="description" content="Drag and drop">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Drag &amp; Drop in Mono Winforms</h1>


<p>
This part of the Mono Winforms tutorial will be dedicated to the drag &amp; 
drop operations. 
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 

<p>
In computer graphical user interfaces, drag-and-drop is the action of 
(or support for the action of) clicking on a virtual object and dragging 
it to a different location or onto another virtual object. In general, it 
can be used to invoke many kinds of actions, or create various types of 
associations between two abstract objects. (Wikipedia)
</p>

<p>
Drag and drop functionality is one of the most visible aspects of the 
graphical user interface. Drag and drop operation enables you to do 
complex things intuitively. 
</p>


<h2>Dragging a button</h2>

<p>
In the first example, we will do the drag &amp; drop operation on the button control. 
The example does the job outside the drag &amp; drop protocol. 
</p>

<div class="codehead">dragbutton.cs</div>
<pre class="code">
using System;
using System.Drawing;
using System.Windows.Forms;

public class MForm : Form
{
  private bool isDragging = false;
  private int oldX, oldY;
  private Button button;

  public MForm()
  {
    Text = "Drag &amp; drop button";
    Size = new Size(270, 180);

    button = new Button();
    button.Parent = this;
    button.Cursor = Cursors.Hand;
    button.Text = "Button";
    button.Location = new Point(20, 20);

    button.MouseDown += new MouseEventHandler(OnMouseDown);
    button.MouseUp += new MouseEventHandler(OnMouseUp);
    button.MouseMove += new MouseEventHandler(OnMouseMove);

    CenterToScreen();
  }

  public static void Main() 
  {
    Application.Run(new MForm());
  }

  private void OnMouseDown(object sender, MouseEventArgs e) 
  {
    isDragging = true;
    oldX = e.X;
    oldY = e.Y;
  }

  private void OnMouseMove(object sender, MouseEventArgs e) 
  {
    if (isDragging) 
    {
        button.Top = button.Top + (e.Y - oldY); 
        button.Left = button.Left + (e.X - oldX); 
    }
  }

  private void OnMouseUp(object sender, MouseEventArgs e) 
  {
    isDragging = false;
  }
}
</pre>


<p>
The code example puts a regular button control on the form container. By 
clicking on the button surface and simultaneously dragging it with
a mouse we can relocate the button. 
</p>


<pre class="explanation">
  private bool isDragging = false;
  private int oldX, oldY;
</pre>

<p>
These are the supporting variables for our example. The <b class="keyword">isDragging</b> 
variable tells us, whether we are in the process of dragging an object. 
The <b class="keyword">oldX</b> and <b class="keyword">oldY</b> variables
store the x, y coordinates just before the dragging process begins. 
</p>

<pre class="explanation">
  button.MouseDown += new MouseEventHandler(OnMouseDown);
  button.MouseUp += new MouseEventHandler(OnMouseUp);
  button.MouseMove += new MouseEventHandler(OnMouseMove);
</pre>

<p>
We plug in three different mouse handlers for our button. They implement three 
different stages of the drag &amp; drop process. The process begins, when we click 
on the button. This is handled by the <b class="keyword">OnMouseDown()</b> method. The second
part is the movement. This is when we move the object to a new position. It is handled in 
the <b class="keyword">OnMouseMove()</b> method. The final part is when the process stops. 
It happens when we release the mouse button. The appropriate
task is delegated to the <b class="keyword">OnMouseUp()</b> method.
</p>

<pre class="explanation">
  private void OnMouseDown(object sender, MouseEventArgs e) 
  {
    isDragging = true;
    oldX = e.X;
    oldY = e.Y;
  }
</pre>

<p>
The <b class="keyword">OnMouseDown()</b> method implements the first part 
of the process. It sets three necessary variables. 
</p>


<pre class="explanation">
  private void OnMouseMove(object sender, MouseEventArgs e) 
  {
    if (isDragging) 
    {
        button.Top = button.Top + (e.Y - oldY); 
        button.Left = button.Left + (e.X - oldX); 
    }
  }

</pre>

<p>
In the <b class="keyword">OnMouseMove()</b> method, we relocate the button. 
We calculate the difference between the stored x, y coordinates and the new 
coordinates of the mouse pointer. The difference is added to the <b class="keyword">Top</b> and 
<b class="keyword">Left</b> properties of the button, thus moving it to a new position.
</p>

<br>
<img src="/img/gui/sharpwinf/dragbutton.png" alt="Dragging a button">
<div class="figure">Figure: Dragging a button</div>


<h2>Dragging Text</h2>

<p>
In the previous example, we did drag &amp; drop on the control. Next we will do 
a drag &amp; drop operation on the textual data. 
Here we will use the drag &amp; drop protocol provided by the Winforms library.
</p>

<p>
Drag &amp; drop operation is a standardized communication protocol in Winforms. 
We have two basic objects. The <b>drag source</b> and
the <b>drop target</b>.  
</p>

<div class="codehead">dragtext.cs</div>
<pre class="code">
using System;
using System.Drawing;
using System.Windows.Forms;

public class MForm : Form
{

    private TextBox textBox;
    private Button button;

    public MForm()
    {
        InitForm();
        CenterToScreen();
    }

    private void OnMouseDown(object sender, MouseEventArgs e)
    {
        TextBox txt = (TextBox) sender;
        txt.DoDragDrop(txt.Text, DragDropEffects.Copy);
    }

    private void OnDragEnter(object sender, DragEventArgs e)
    {
        e.Effect = DragDropEffects.Copy;
    }

    private void OnDragDrop(object sender, DragEventArgs e)
    {
        Button button = (Button) sender;
        button.Text = (string) e.Data.GetData(DataFormats.Text);
    }


    private void InitForm()
    {
        Text = "Drag & drop";
        button = new Button();
        textBox = new TextBox();
        SuspendLayout();

        button.AllowDrop = true;
        button.Location = new Point(150, 50);
        textBox.Location = new Point(15, 50);

        button.DragDrop += new DragEventHandler(OnDragDrop);
        button.DragEnter += new DragEventHandler(OnDragEnter);
        textBox.MouseDown += new MouseEventHandler(OnMouseDown);

        ClientSize = new Size(250, 200);
        Controls.Add(button);
        Controls.Add(textBox);
        ResumeLayout();
    }

    public static void Main(string[] args)
    {
        Application.Run(new MForm());
    }

}
</pre>

<p>
We have two controls on the form. A button and a text box. We will drag text from 
the text box and drop it on the button. 
</p>


<pre class="explanation">
 InitForm();
</pre>

<p>
Setting up of the form is delegated to the <b class="keyword">InitForm()</b> method. 
This is usually done in larger
applications. 
</p>

<pre class="explanation">
 SuspendLayout();
 ...
 ResumeLayout();
</pre>

<p>
We lay out our controls between these two method calls. This is an optimalization. 
It should eliminate flicker.
</p>

<pre class="explanation">
 button.AllowDrop = true;
</pre>

<p>
We set the <b class="keyword">AllowDrop</b> property to true. Dropping is not 
enabled by default. 
</p>

<pre class="explanation">
 button.DragDrop += new DragEventHandler(OnDragDrop);
 button.DragEnter += new DragEventHandler(OnDragEnter);
 textBox.MouseDown += new MouseEventHandler(OnMouseDown);
</pre>

<p>
Again, the drag &amp; drop process is divided into three steps. We have three 
methods for each particular step. 
</p>

<pre class="explanation">
 private void OnMouseDown(object sender, MouseEventArgs e)
 {
     TextBox txt = (TextBox) sender;
     txt.DoDragDrop(txt.Text, DragDropEffects.Copy);
 }
</pre>

<p>
In the <b class="keyword">OnMouseDown()</b> method we initialize the drap &amp; 
drop process. We initiate the process with the <b class="keyword">DoDragDrop()</b> 
method. The <b class="keyword">DragDropEffects.Copy</b>
parameter specifies the type of the operation. Esentially, we can either copy the 
text or move it during the drag &amp; drop operation. 
</p>

<pre class="explanation">
 private void OnDragEnter(object sender, DragEventArgs e)
 {
     e.Effect = DragDropEffects.Copy;
 }
</pre>

<p>
The <b class="keyword">DragEnter</b> event is launched when the mouse pointer 
enters the area of the drop target control. The <b class="keyword">Effect</b> 
property must be set. The DragDropEffects of the drag source and drop target must be equal.
Otherwise the operation will not work. 
</p>


<pre class="explanation">
 private void OnDragDrop(object sender, DragEventArgs e)
 {
     Button button = (Button) sender;
     button.Text = (string) e.Data.GetData(DataFormats.Text);
 }
</pre>

<p>
Finally we have the <b class="keyword">OnDragDrop()</b> method. Here we get
the data from the event object and
set it to the button <b class="keyword">Text</b> property.
</p>


<br>
<img src="/img/gui/sharpwinf/dragtext.png" alt="Drag & drop of text">
<div class="figure">Figure: Drag &amp; drop of text</div>



<h2>Dragging Image</h2>

<p>
In our last example, we will drag &amp; drop image on the form. 
</p>


<div class="codehead">dragimage.cs</div>
<pre class="code">
using System;
using System.Drawing;
using System.Windows.Forms;

public class ImageDragDrop : Form
{
  private bool isDragging;
  private int oldX, oldY;

  private Rectangle dropRect;
  private PictureBox picBox;
  private Bitmap image;
  private Brush brush;

  public ImageDragDrop()
  {
    ClientSize = new Size(350, 250);
    Text = "Dragging Image";
    Paint += new PaintEventHandler(OnPaint);
    
    isDragging = false;
    dropRect = new Rectangle(10, 10, 200, 160);
    brush = Brushes.Gray;
    picBox = new PictureBox();
    loadImage();

    picBox.Parent = this;
    picBox.Location = new Point(100, 50);
    picBox.Size = new Size(image.Width, image.Height);
    picBox.Image = image;
    picBox.Cursor = Cursors.Hand;

    picBox.MouseDown += new MouseEventHandler(OnMouseDown);
    picBox.MouseUp += new MouseEventHandler(OnMouseUp);
    picBox.MouseMove += new MouseEventHandler(OnMouseMove);

    CenterToScreen();
  }


  void loadImage() {
      try {
          image = new Bitmap("image.jpg");
      } catch {
          Console.WriteLine("Error reading image");
          Environment.Exit(1);
      }
  }

  public static void Main() 
  {
    Application.Run(new ImageDragDrop());
  }

  private void OnMouseDown(object sender, MouseEventArgs e) 
  {
    isDragging = true;
    oldX = e.X;
    oldY = e.Y;
  }

  private void OnMouseMove(object sender, MouseEventArgs e) 
  {
    if (isDragging) 
    {
      picBox.Top = picBox.Top + (e.Y - oldY);
      picBox.Left = picBox.Left + (e.X - oldX);
    }
  }

  private void OnMouseUp(object sender, MouseEventArgs e) 
  {
    isDragging = false;

    if(dropRect.Contains(picBox.Bounds)) {
        brush = Brushes.Gold;
    } else {
        brush = Brushes.Gray;
    }

    Refresh();
  }

  private void OnPaint(object sender, PaintEventArgs e)
  {
    Graphics g = e.Graphics;
    g.FillRectangle(brush, dropRect);
  }
}
</pre>

<p>
In our example we have a <b class="keyword">PictureBox</b> and we draw a 
gray rectangle. If we drop the picture inside 
the rectangle, the color of the rectangle changes to gold. 
</p>

<pre class="explanation">
 brush = Brushes.Gray;
</pre>

<p>
The <b class="keyword">brush</b> variable holds the brush of the rectangle. 
It is a gray color by default.  
</p>

<pre class="explanation">
  void loadImage() {
      try {
          image = new Bitmap("image.jpg");
      } catch {
          Console.WriteLine("Error reading image");
          Environment.Exit(1);
      }
  }
</pre>

<p>
The <b class="keyword">loadImage()</b> loads a bitmap for the 
<b class="keyword">PictureBox</b> control.
</p>

<pre class="explanation">
 if (dropRect.Contains(picBox.Bounds)) {
     brush = Brushes.Gold;
 } else {
     brush = Brushes.Gray;
 }
</pre>

<p>
In the <b class="keyword">OnMouseUp()</b> method, we determine the brush of the 
rectangle. If the bounds of the picture box are inside the rectangle, the brush 
is of gold color; gray otherwise.
</p>

<pre class="explanation">
 Refresh();
</pre>

<p>
We must call the <b class="keyword">Refresh()</b> method to activate the new brush color. 
</p>

<br>
<img src="/img/gui/sharpwinf/dragimage.png" alt="Drag &amp; drop image">
<div class="figure">Figure: Drag &amp; drop image</div>

<hr class="btm">

<p>
This chapter was dedicated to drag &amp; drop operations using the Mono Winforms library. 
</p>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 26, 2008  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
